Skip to content

feat: HIIT countdown timer with auto set/rest cycling#82

Open
hozaifa1 wants to merge 2 commits into
LibreFitOrg:mainfrom
hozaifa1:feat/hiit-countdown-timer
Open

feat: HIIT countdown timer with auto set/rest cycling#82
hozaifa1 wants to merge 2 commits into
LibreFitOrg:mainfrom
hozaifa1:feat/hiit-countdown-timer

Conversation

@hozaifa1
Copy link
Copy Markdown

Summary

Adds support for HIIT-style autonomous timer flow on duration-based exercises:

  1. Press play → set countdown begins
  2. Countdown reaches 0 → rest timer auto-starts
  3. Rest reaches 0 → next set countdown auto-starts
  4. Repeats until all sets are complete (no taps in between)

This unlocks Tabata / EMOM / circuit workouts where the user wants hands-free progression through a fixed work/rest cycle.

Changes

Data layer

  • Exercise: new fields targetDuration: Int and autoAdvanceSets: Boolean
  • ExerciseDC: new field cautions: String (common-mistakes text shown to the user)
  • Room MIGRATION_3_4 adds the three new columns (defaults preserve existing rows)
  • UI models (UiExercise, UiExerciseDC) and their mappers updated to match

Service layer

  • WorkoutService gains a countdown coroutine and four new StateFlows:
    countdownTime, isCountdownActive, countdownTotal, countdownFinished
  • Two new actions: START_COUNTDOWN, CANCEL_COUNTDOWN
  • When a countdown finishes, the service auto-starts the rest timer if a rest duration was provided
  • WorkoutServiceManager exposes startCountdown(duration, restDuration) and cancelCountdown()

ViewModel

  • WorkoutScreenViewModel.HiitPhase sealed class: Idle / SetCountdown / RestBetweenSets / ExerciseDone
  • Observers tie the lifecycle together:
    • On countdownFinished → mark the set as completed, transition to RestBetweenSets
    • On rest timer reaching 0 while in RestBetweenSets → start the next set's countdown
  • startHiitCountdown / cancelHiitCountdown / resetHiitPhase for screen control

UI

  • New HiitCountdownCard composable with a circular progress arc and color-coded phase
    • orange = set, red = last 3 seconds, blue = rest, green = done
    • controls: Start Set / Cancel / Skip Rest / Info
  • WorkoutScreen renders the card above the regular ExerciseCard for any exercise where
    setMode == DURATION && targetDuration > 0 && autoAdvanceSets
  • InfoExerciseScreen shows a "Common Mistakes" warning card on the Instructions tab when
    cautions is non-empty (no-op for legacy exercises with empty cautions)

Backward compatibility

  • All new entity fields default to 0 / false / "" so legacy workouts are unaffected
  • Existing rest-timer behaviour is unchanged when autoAdvanceSets is false
  • The HIIT card only appears for exercises that explicitly opt in

Test plan

  • Fresh install: DB created at v4, app launches normally
  • Upgrade from v3: migration runs, existing workouts open without crashes
  • Create a DURATION exercise with targetDuration=30, restTime=15, autoAdvanceSets=true, 3 sets
    • Tap Start Set → arc counts 30 → 0 with orange color
    • Last 3 s turn red
    • Rest auto-starts in blue, counts 15 → 0
    • Next set begins automatically; cycle repeats for set 3
    • After final set, phase shows "DONE" / green
  • Tap Cancel mid-countdown → returns to idle, set NOT marked complete
  • Tap Skip Rest during rest → next set's countdown begins immediately
  • Tap Info → navigates to InfoExerciseScreen
  • Backgrounding the app during a countdown keeps the foreground notification alive
  • Existing non-HIIT (LOAD / BODYWEIGHT) flow unaffected
  • InfoExerciseScreen: stock exercises with empty cautions show no warning card; an exercise with cautions set shows the red warning card on the Instructions tab

Notes

UI to edit targetDuration / autoAdvanceSets from the Edit-Exercise screen is not included in this PR — the fields are wired through the data and service layers and the runtime UI, but a follow-up PR can add the form controls. For now they can be set programmatically or via custom-exercise creation. Happy to split this further or fold the edit UI in if maintainers prefer.

Adds support for HIIT-style autonomous timer flow:
- Press play -> set countdown begins
- Countdown reaches 0 -> rest timer auto-starts
- Rest reaches 0 -> next set countdown auto-starts
- Repeats until all sets are complete

Implementation:
- New Exercise fields: targetDuration (sec), autoAdvanceSets (bool)
- New ExerciseDC field: cautions (common-mistakes text shown in info screen)
- Room migration 3 -> 4 for the three new columns
- WorkoutService gains countdown coroutine + StateFlows
  (countdownTime, isCountdownActive, countdownTotal, countdownFinished)
- New service actions: START_COUNTDOWN, CANCEL_COUNTDOWN
- WorkoutScreenViewModel: HiitPhase sealed class
  (Idle / SetCountdown / RestBetweenSets / ExerciseDone) plus observers
  that mark sets complete and auto-advance on rest expiry
- New HiitCountdownCard composable: circular arc + phase label +
  play / cancel / skip-rest controls (orange=set, blue=rest, red=last 3s,
  green=done)
- WorkoutScreen renders the card for DURATION exercises with
  targetDuration > 0 and autoAdvanceSets enabled
- InfoExerciseScreen shows a "Common Mistakes" warning card when the
  exercise has non-empty cautions
Copy link
Copy Markdown
Member

@IamDg IamDg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very disappointed by this work: no encapsulation, no testing, no compose previews, no best practices, just hardcoding, spaghetti code and vide coding! In addition, it doesn't build in CI and the actual feature in the app is even inaccessible as there isn't a way for the user to enter HIIT mode. Please, invest actual effort and time if you actually want to add real value to the project.

…iews

Address review feedback on commit 127c7e5:

- Add HiitSettingsCard exposed in the workout screen for DURATION
  exercises so users can actually enable HIIT auto-advance and pick
  a target duration. Without this the feature was unreachable.
- Extract HiitPhase to a top-level sealed class with a pure
  nextPhaseAfterCountdown transition helper; unit-test the helper.
- Rewrite HiitCountdownCard to use existing drawable resources and
  MaterialTheme.colorScheme instead of dragging in the unavailable
  androidx.compose.material:material-icons-extended library and
  hard-coding hex colours.
- Move every user-facing HIIT string to strings.xml.
- Add @Preview functions for all visual HIIT components (idle, set,
  rest, done, settings on/off).
- Drop the ExerciseDC.cautions field and its 3->4 migration column.
  The dataset schema is defined by schemas/exercise-schema.json and
  must not be extended here; the field also had no UI to populate it.
- Add a SessionStart hook so subsequent web sessions can run
  lintDebug, testDebugUnitTest, and assembleDebug locally.
- Regenerate app/lint-baseline.xml: Room-generated code shifts line
  numbers when columns are added to the exercises entity. Stripped
  environment-only entries (AGP/Gradle/dependency-version notices).

Verified locally with:
  ./gradlew lintDebug
  ./gradlew testDebugUnitTest
  ./gradlew assembleDebug
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants